package model

import (
	"errors"
	"fmt"
	"ordersystem/config"
	"ordersystem/database"
	"time"
)

type Lab struct {
	Id       int32     `json:"id" xml:"id" form:"id" gorm:"primaryKey"`
	Tag      string    `json:"tag" xml:"tag" form:"tag"`
	Label    string    `json:"label" xml:"label" form:"label"`
	Size     int       `json:"size" xml:"size" form:"size"`
	Creator  int32     `json:"creator" xml:"creator" form:"creator"`
	Function string    `json:"function" xml:"function" form:"function"`
	Location string    `json:"location" xml:"location" form:"location"`
	CreateAt time.Time `json:"create_at" xml:"create_at" form:"create_at" gorm:"autoCreateTime"`
	UpdateAt time.Time `json:"update_at" xml:"update_at" form:"update_at" gorm:"autoUpdateTime"`
}

func (lab *Lab) QueryLab() error {
	conn := database.GetMysqlConnection()
	fmt.Println(lab)
	conn.Model(&lab).First(lab)
	return nil
}

func (lab *Lab) QueryDetailLab() (map[string]interface{}, error) {
	conn := database.GetMysqlConnection()
	var result []map[string]interface{}
	fmt.Println(lab.Id)
	conn.Model(&lab).Select("labs.*,users.name as creator_name,users.telphone").Joins("left join users on users.id = labs.creator").Scan(&result)
	return result[0], nil
}

func QueryLabNumber(id int32) (int64, error) {
	conn := database.GetMysqlConnection()
	var result int64

	if id == 0 {
		conn.Table(config.TABLE_LABS).Count(&result)
		return result, nil
	} else {
		conn.Table(config.TABLE_LABS).Where("creator = ?", id).Count(&result)
		return result, nil
	}

}

func QueryByLabIdAndDate(labId int32, date time.Time) (interface{}, error) {
	conn := database.GetMysqlConnection()

	var result []map[string]interface{}

	conn.Table(config.TABLE_LABS).Where(" id = ? ", labId).Scan(&result)
	var orders []map[string]interface{}

	fmt.Println("result", labId, result)

	// sql := conn.ToSQL(func(tx *gorm.DB) *gorm.DB {
	// 	return tx.Table(config.TABLE_ORDERS).Where("lab_id = ? and start > ? AND end < DATE_ADD(?, INTERVAL 1 DAY)", labId, date, date).Scan(&orders)
	// })
	// fmt.Println("sql", sql)
	conn.Table(config.TABLE_ORDERS).Where("lab_id = ? and start > ? AND end < DATE_ADD(?, INTERVAL 1 DAY)", labId, date, date).Scan(&orders)

	fmt.Println("orders:", orders)
	if len(orders) != 0 {
		result[0]["order"] = orders
	}

	return result[0], nil
}

func QueryByTagAndDate(tag string, date time.Time) ([]map[string]interface{}, error) {

	var number int
	conn := database.GetMysqlConnection()
	var result []map[string]interface{}
	conn.Table(config.TABLE_LABS).Where("tag = ?", tag).Scan(&result)
	number = len(result)
	ch := make(chan int, number)
	for i := 0; i < number; i++ {
		go func(j int) {
			var orders []map[string]interface{}
			conn.Table(config.TABLE_ORDERS).Where("lab_id = ? and start > ? AND end < DATE_ADD(?, INTERVAL 1 DAY)", result[j]["id"], date, date).Scan(&orders)
			fmt.Println("orders:", orders)
			if len(orders) != 0 {
				result[j]["order"] = orders
			}
			ch <- 1
		}(i)
	}

	for i := 0; i < number; i++ {
		<-ch
	}
	return result, nil
}

func QueryLabsForAdminOrSuperAdmin(page int, id int32) (interface{}, error) {
	conn := database.GetMysqlConnection()

	var result []map[string]interface{}
	if id == 0 {
		conn.Model(&Lab{}).Offset(config.PAGE_SIZE * page).Limit(config.PAGE_SIZE).Scan(&result)
		return result, nil
	} else {
		conn.Model(&Lab{}).Where("creator", id).Offset(config.PAGE_SIZE * page).Limit(config.PAGE_SIZE).Scan(&result)
		return result, nil
	}
}

func (lab *Lab) CreateLab() error {
	conn := database.GetMysqlConnection()

	affectedRows := conn.Model(lab).Create(lab).Commit().RowsAffected
	if affectedRows == 0 {
		return errors.New(config.RESPONSE_DATABASE_OPERATION_ERROR)
	}
	return nil
}

func (lab *Lab) UpdateLab() error {
	conn := database.GetMysqlConnection()

	conn.Model(lab).Save(lab).Commit()

	return nil
}

func LabQueryTag() []map[string]interface{} {
	conn := database.GetMysqlConnection()

	var result []map[string]interface{}

	conn.Table(config.TABLE_LABS).Select("distinct tag").Scan(&result)
	return result
}

func (lab *Lab) DeleteLab() error {
	conn := database.GetMysqlConnection()

	if conn.Model(lab).Delete(lab).Commit().RowsAffected == 0 {
		return errors.New(config.RESPONSE_DATABASE_OPERATION_ERROR)
	}
	return nil
}
